package si.assign2.model;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

//import com.sun.jmx.snmp.Timestamp;

@Entity
@Table(name="categories")
@NamedQueries({
    @NamedQuery(name="listCategories",
                query="SELECT c FROM Category c"),
    @NamedQuery(name="getCategoriesById",
                query="SELECT c FROM Category c WHERE c.id = :id"),
    @NamedQuery(name="getCategoriesByName",
                query="SELECT c FROM Category c WHERE c.name = :name"),
    @NamedQuery(name="getCategoriesByNameAndProductType",
                query="SELECT c FROM Category c WHERE c.name = :name " +
                		"and c.productType=:productType")
})
public class Category 
{
	public Category(){}
	
	/*
	 * Properties
	 */
	
	/*
	 * Set and get id
	 */
	public int getId()
	{	return id;     }
	public void setId(int id)
	{   this.id = id;  }

	/*
	 * Set and get parent_id
	 */
	public Category getParent()
	{   return this.parent;   }
	public void setParent(Category parent)
	{   this.parent = parent;  }
	
	public void addChild(Category child) {
		this.children.add(child);
		child.setParent(this);
	}
	public Set<Category> getChildren() {
		return this.children;
	}
	
	/*
	 * Set and get name
	 */
	public String getName()
	{   return name;   }
	public void setName(String name)
	{   this.name = name;  }
	
	/*
	 * Set and get Product_type
	 */
	public ProductType getProductType()
	{	return productType;	}	
	public void setProductType(ProductType productType)	{
		this.productType = productType;
	}
	
	/**
	 * @return products associated
	 */
	public Set<Product> getProducts() {
		return this.products;
	}
	
	/**
	 * @param products the set of products to set
	 */
	public void setProducts(Set<Product> products) {
		this.products = products;
	}
	
	/**
	 * @param productCategory the product category to add
	 */
	public void addProduct(Product product) {
		this.products.add(product);
		product.getCategories().add(this);
	}
	
	/**
	 * @param productCategory the product category to remove
	 */
	public void removeProduct(Product product) {
		this.products.remove(product);
		product.getCategories().remove(this);
	}
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Basic(optional=false)
	@Column(name="id", nullable=false)
	private int id;
	
	@Column(name="name", length = 255, nullable=false)
	private String name;

	/*
	 * Many-to-one mapping from Category to ProductType
	 * <remarks>
	 *  nullable value should be false for this field if the table spec is considered
	 *  however if id in product_types table starts from 0 this needs to be set to true,
	 *  fortunately we also made some changes to the product_types table to make it
	 *  fulfill the non-nullable requirement, we can keep on using nullable being false. 
	 * </remarks>
	 */
	@ManyToOne(optional=false, fetch=FetchType.LAZY, cascade=CascadeType.ALL)
	@JoinColumn(name="product_type", nullable=false)
	private ProductType productType;
		
  	/*
  	 * One-to-one mapping from Category to Category
  	 */
  	@ManyToOne(optional=false, fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
  	@JoinColumn(name="parent_id", unique=true, nullable=false, updatable=false)
  	private Category parent;
  	
  	@OneToMany(mappedBy="parent")
  	private Set<Category> children = new HashSet<Category>();
	
	
	/*
	 * Many-to-many mapping from Category to Product
	 * Product is relationship owner
	 */
	@ManyToMany(mappedBy="categories", cascade=CascadeType.ALL)
	@JoinTable(
			name="product_categories",
			joinColumns=@JoinColumn(name="product_id", referencedColumnName="id"),
			inverseJoinColumns=@JoinColumn(name="category_id", referencedColumnName="id")
	)
	private Set<Product> products = new HashSet<Product>();
	
}
